﻿#define _CRT_SECURE_NO_WARNINGS 1
//*************************指针****************************//

//字符指针变量
//int main()
//{
//	const char* pstr = "hello bit.";//这里是把一个字符串放到pstr指针变量里了吗？把字符串 hello bit. 首字符的地址放到了pstr中
//	printf("%s\n", pstr);
//	return 0;
//}

//#include <stdio.h>
//int main()
//{
//	char str1[] = "hello bit.";
//	char str2[] = "hello bit.";
//	const char* str3 = "hello bit.";
//	const char* str4 = "hello bit.";
//	if (str1 == str2)
//		printf("str1 and str2 are same\n");
//	else
//		printf("str1 and str2 are not same\n");
//
//	if (str3 == str4)
//		printf("str3 and str4 are same\n");
//	else
//		printf("str3 and str4 are not same\n");
//
//	return 0;
//}
//这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域，
//当几个指针指向同一个字符串的时候，他们实际会指向同一块内存。但是用相同的常量字符串去初始
//化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同，str3和str4相同。


//数组指针变量
//int* p1[10];//指针数组
//int(*p2)[10];//数组指针

//int arr[10] = { 0 };
//&arr;//得到的就是数组的地址
////如果要存放个数组的地址，就得存放在数组指针变量中，如下：
//int(*p)[10] = &arr;


//二维数组传参的本质
//#include <stdio.h>
//void test(int a[3][5], int r, int c)
//{
//	int i = 0;
//	int j = 0;
//	for (i = 0; i < r; i++)
//	{
//		for (j = 0; j < c; j++)
//		{
//			printf("%d ", a[i][j]);
//		}
//		printf("\n");
//	}
//}
//int main()
//{
//	int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7} };
//	test(arr, 3, 5);
//	return 0;
//}
// 二维数组其实可以看做是每个元素是一维数组的数组，也就是二维数组的每个元素是一个一维数组。那么二维数组的首元素就是第一行，是个一维数组。

//根据数组名是数组首元素的地址这个规则，二维数组的数组名表示的就是第一行的地址，是一
//维数组的地址。根据上面的例子，第⼀行的⼀维数组的类型就是 int[5] ，所以第一行的地址的类
//型就是数组指针类型 int(*)[5] 。那就意味着二维数组传参本质上也是传递了地址，传递的是第⼀
//行这个一维数组的地址，那么形参也是可以写成指针形式的。如下：
//#include <stdio.h>
//void test(int (*p)[5], int r, int c)
//{
//	int i = 0;
//	int j = 0;
//	for (i = 0; i < r; i++)
//	{
//		for (j = 0; j < c; j++)
//		{
//			printf("%d ", *(*(p + i) + j));
//			//printf("%d ", p[i][j]);
//		}
//		printf("\n");
//	}
//}
//int main()
//{
//	int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7} };
//	test(arr, 3, 5);
//	return 0;
//}
//总结：二维数组传参，形参的部分可以写成数组，也可以写成指针形式


//函数指针变量
//函数指针变量应该是用来存放函数地址的，未来通过地址能够调用函数的。
//#include <stdio.h>
//void test()
//{
//	printf("hehe\n");
//}
//int main()
//{
//	printf("test: %p\n", test);
//	printf("&test: %p\n", &test);
//	return 0;
//}
//函数是有地址的，函数名就是函数的地址，当然也可以通过&函数名的方式获得函数的地址。

//void test()
//{
//	printf("hehe\n");
//}
//void (*pf1)() = &test;
//void (*pf2)() = test;
//int Add(int x, int y)
//{
//	return x + y;
//}
//int(*pf3)(int, int) = Add;
//int(*pf3)(int x, int y) = &Add;//x和y写上或者省略都是可以的

//#include <stdio.h>
//int Add(int x, int y)
//{
//	return x + y;
//}
//int main()
//{
//	int (*p)(int, int) = Add;
//	printf("%d\n", (*p)(2, 3));
//	printf("%d\n", p(2, 3));
//	return 0;
//}


//typedef 关键字
//typedef 是用来类型重命名的，可以将复杂的类型，简单化。
//typedef unsigned int uint;
//将unsigned int 重命名为uint

//typedef int* ptr_t;//将 int* 重命名为 ptr_t
////将int(*)[5], 重命名为 parr_t
//typedef int(*parr_t)[5]; //新的类型名必须在*的右边
////将 void(*)(int) 类型重命名为 pfun_t
//typedef void(*pfun_t)(int);//新的类型名必须在*的右边


//函数指针数组
//int* arr[10];
//数组的每个元素是int*
//那要把函数的地址存到⼀个数组中，那这个数组就叫函数指针数组，那函数指针的数组如何定义呢？
//int (*parr1[3])();
//int* parr2[3]();
//int (*)() parr3[3];
//答案是：parr1
//parr1 先和[] 结合，说明 parr1是数组，数组的内容是什么呢？是 int (*)() 类型的函数指针。


//转移表
//函数指针数组的用途：转移表
//举例：计算器的⼀般实现：
//#include <stdio.h>
//int add(int x, int y)	//加
//{
//	return x + y;
//}
//int sub(int x, int y)	//减
//{
//	return x - y;
//}
//int mul(int x, int y)	//乘
//{
//	return x * y;
//}
//int div(int x, int y)	//除
//{
//	return x / y;
//}
//int main()
//{
//	int x = 0;
//	int y = 0;
//	int input = 1;
//	int result = 0;
//	do
//	{
//		printf("*********************\n");
//		printf("*****1.加   2.减*****\n");
//		printf("*****3.乘   4.除*****\n");
//		printf("*****  0. 退出  *****\n");
//		printf("*********************\n");
//		printf("请输入操作的序号:");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 0:
//			printf("退出计算器!\n");
//			break;
//		case 1:
//			printf("输入操作数:");
//			scanf("%d %d", &x, &y);
//			result = add(x, y);
//			printf("%d\n", result);
//			break;
//		case 2:
//			printf("输入操作数:");
//			scanf("%d %d", &x, &y);
//			result = sub(x, y);
//			printf("%d\n", result);
//			break;
//		case 3:
//			printf("输入操作数:");
//			scanf("%d %d", &x, &y);
//			result = mul(x, y);
//			printf("%d\n", result);
//			break;
//		case 4:
//			printf("输入操作数:");
//			scanf("%d %d", &x, &y);
//			result = div(x, y);
//			printf("%d\n", result);
//			break;
//		default:
//			printf("输入错误，请重新输入!\n");
//			break;
//		}
//	} while (input);
//
//	return 0;
//}

//使用函数指针的实现(回调函数)：
//#include <stdio.h>
//int add(int x, int y)	//加
//{
//	return x + y;
//}
//int sub(int x, int y)	//减
//{
//	return x - y;
//}
//int mul(int x, int y)	//乘
//{
//	return x * y;
//}
//int div(int x, int y)	//除
//{
//	return x / y;
//}
//void calc(int (*p)(int, int))
//{
//	int result = 0;
//	int x = 0;
//	int y = 0;
//	printf("输入操作数:");
//	scanf("%d %d", &x, &y);
//	result = p(x, y);
//	printf("%d\n", result);
//}
//int main()
//{
//	int input = 1;
//	do
//	{
//		printf("*********************\n");
//		printf("*****1.加   2.减*****\n");
//		printf("*****3.乘   4.除*****\n");
//		printf("*****  0. 退出  *****\n");
//		printf("*********************\n");
//		printf("请输入操作的序号:");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 0:
//			printf("退出计算器!\n");
//			break;
//		case 1:
//			calc(add);
//			break;
//		case 2:
//			calc(sub);
//			break;
//		case 3:
//			calc(mul);
//			break;
//		case 4:
//			calc(div);
//			break;
//		default:
//			printf("输入错误，请重新输入!\n");
//			break;
//		}
//	} while (input);
//
//	return 0;
//}

//使用函数指针数组的实现:
//#include <stdio.h>
//int add(int x, int y)	//加
//{
//	return x + y;
//}
//int sub(int x, int y)	//减
//{
//	return x - y;
//}
//int mul(int x, int y)	//乘
//{
//	return x * y;
//}
//int div(int x, int y)	//除
//{
//	return x / y;
//}
//void calc(int (*p)(int, int))
//{
//	int result = 0;
//	int x = 0;
//	int y = 0;
//	printf("输入操作数:");
//	scanf("%d %d", &x, &y);
//	result = p(x, y);
//	printf("%d\n", result);
//}
//int main()
//{
//	int x = 0;
//	int y = 0;
//	int result = 0;
//	int input = 1;
//	int (*p[5])(int, int) = { 0,add,sub,mul,div };
//	do
//	{
//		printf("*********************\n");
//		printf("*****1.加   2.减*****\n");
//		printf("*****3.乘   4.除*****\n");
//		printf("*****  0. 退出  *****\n");
//		printf("*********************\n");
//		printf("请输入操作的序号:");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 0:
//			printf("退出计算器!\n");
//			break;
//		case 1:
//		case 2:
//		case 3:
//		case 4:
//			printf("请输入操作数:");
//			scanf("%d %d", &x, &y);
//			result = p[input](x, y);
//			printf("%d\n", result);
//			break;
//		default:
//			printf("输入错误，请重新输入!\n");
//			break;
//		}
//	} while (input);
//
//	return 0;
//}





